import java.util.Scanner;

public class demo {
    // 红与黑▲▲▲▲▲
//有一间长方形的房子，地上铺了红色、黑色两种颜色的正方形瓷砖。你站在其中一块黑色的瓷砖上，只能向相邻的（上下左右四个方向）黑色瓷砖移动。
//请写一个程序，计算你总共能够到达多少块黑色的瓷
//    输入描述:
//输入包含多组数据。
//每组数据第一行是两个整数 n 和 m（1≤m, n≤20）。紧接着 n 行，每行包括 m 个字符。每个字符表示一块瓷砖的颜色，规则如下：
//1. “.”：黑色的瓷砖；
//2. “#”：白色的瓷砖；
//3. “@”：黑色的瓷砖，并且你站在这块瓷砖上。该字符在每个数据集合中唯一出现一次。
//    输出描述:
//对应每组数据，输出总共能够到达多少块黑色的瓷砖。
//    输入
//9 6
//....#.
//.....#
//......
//......
//......
//......
//......
//#@...#
//.#..#.
//    输出
//45

    public static int count;
    public static void dfs(char[][] map, int n, int m, int x, int y) {
        if (x<0 || x>=n || y<0 || y>=m ||
                map[x][y]=='#') {
            return;
        }
        // 走到这里 就可以站到该位置上
        count++;

        // 标记 证明我们已经走过该位置
        map[x][y] = '#';
        // 在判断其他位置是否可以站(是黑色 就是符号.)
        dfs(map, n, m, x-1, y);
        dfs(map, n, m, x+1, y);
        dfs(map, n, m, x, y-1);
        dfs(map, n, m, x, y+1);
    }

    public static void main1(String[] args) {
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNext()) {
            int n = scanner.nextInt();
            int m = scanner.nextInt();
            char[][] map = new char[n][m];
            // 判断如果不存在这个长方形 就continue
            if (n*m == 0) {
                continue;
            }
            // 出发点位置
            int x = 0;
            int y = 0;

            for (int i=0; i<n; i++) {
                // 一行一行的接收
                String str = scanner.next();
                for (int j=0; j<m; j++) {
                    map[i][j] = str.charAt(j);
                    // 寻找出发点位置
                    if (str.charAt(j) == '@') {
                        x = i;
                        y = j;
                    }
                }
            }
            // 用静态属性来保存 每走过的值 因为是多组输入 所以每次进来 count都要初始化为0
            count = 0;
            dfs(map, n, m, x, y);
            System.out.println(count);
        }
    }




    //  蘑菇阵▲▲▲▲▲
//现在有两个好友A和B，住在一片长有蘑菇的由n＊m个方格组成的草地，A在(1,1),B在(n,m)。现在A想要拜访B，由于她只想去B的家，
//所以每次她只会走(i,j+1)或(i+1,j)这样的路线，在草地上有k个蘑菇种在格子里(多个蘑菇可能在同一方格),
//问：A如果每一步随机选择的话(若她在边界上，则只有一种选择)，那么她不碰到蘑菇走到B的家的概率是多少？
//    输入描述:
//第一行N，M，K(1 ≤ N,M ≤ 20, k ≤ 100),N,M为草地大小，接下来K行，每行两个整数x，y，代表(x,y)处有一个蘑菇。
//    输出描述:
//输出一行，代表所求概率(保留到2位小数)

//输入
//2 2 1
//2 1
//输出
//0.50
//    思路:
//1. 循环接受输入(注意：一般IO类型算法即需要写main的算法，背后可能有多个测试用例，每个用例必须测试到，因此需要循环输入)
//2. 按照输入构造蘑菇地图(二维矩阵)，1代表蘑菇，0代表通路，因起点是从(1,1)开始，矩阵多给一个行和列
//3. 构造用来保存走到(i,j)位置不遇到蘑菇的概率容器
//4. 按照上述分析结论：遍历蘑菇地图，当遇到蘑菇时，将概率置为0，即不可能到达该位置
//5. 按照要求输出：注意保留两位精度。

    // 经过每个点的概率
    public static double probable(int[][] map, int n, int m) {
        double[][] flag = new double[n+1][m+1];
        flag[1][1] = 1.0;
        for (int i=1; i<=n; i++) {
            for (int j=1; j<=m; j++) {
                // 跳过起始点
                if (i!=1 || j!=1) {
                    // 这里条件运算符  内容不能搞混了
                    flag[i][j] = flag[i][j-1]*(i==n? 1.0 : 0.5) + flag[i-1][j]*(j==m? 1.0 : 0.5);
                    // 如果该点有蘑菇 那么就将该点概率改成0  在之后经过该路 0乘任何数都等于0
                    if (map[i-1][j-1] == 1) {
                        flag[i][j] = 0.0;
                    }
                }
            }
        }
        return flag[n][m];
    }
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNextInt()) {
            // 先创建蘑菇阵地图
            int n = scanner.nextInt();
            int m = scanner.nextInt();
            int k = scanner.nextInt();
            int[][] map = new int[n][m];
            for (int i=0; i<k; i++) {
                int x = scanner.nextInt();
                int y = scanner.nextInt();
                // 表示该点有蘑菇
                map[x-1][y-1] = 1;
            }

            // 判断经过该点的概率
            double flag = probable(map, n, m);
            System.out.printf("%.2f", flag);
            System.out.println();
        }
    }
}
